/**
 * java frame work of system utils
 * the module supply file operation,datetime converter
 * @author create by lms 2016.04.01
 * @author update lms 2016.07.05
 */
package ms.core.tool;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.UUID;

public class SysTool {

	//////////////////////////////// file system ////////////////////////////////////
	final static public int WINDOWS = 0;
	final static public int LINUX 	= 1;
	final static public int UNIX	= 2;
	final static public int MAC 	= 3;
	final static public int SOLARIS = 4;

	public static int getOSType(){
		String ret = System.getProperty("os.name").toLowerCase();
		if (ret.indexOf("windows")>=0) return WINDOWS;
		if (ret.indexOf("linux")>=0) return LINUX;
		if (ret.indexOf("unix")>=0) return UNIX;
		if (ret.indexOf("mac")>=0) return MAC;
		if (ret.indexOf("solaris")>=0) return SOLARIS;

		return -1;
	}

	/**
	 * 判断指定文件或文件夹是否存在
	 * @param fileName 
	 * @return -1:exception; 0-not exists; 1- exists */
	public static int fileExists(String fileName){
		if (StrTool.isBlank(fileName)) 
			return -1;

		try{
			File file=new File(fileName);
			return (file.exists()) ? 1 : 0;
		}catch(Exception e){
			Log4j2Tool.error(SysTool.class, "fileExists:", e);
			return -1;
		}
	}

	/**
	 * 文件删除操作
	 * @param fileName
	 * @return
	 */
	public static boolean deleteFile(String fileName) {
		try {
			File file=new File(fileName);
			if (file.exists() && file.isFile()) {
				file.delete();
				return true;
			}
		}catch(Exception e){
			Log4j2Tool.error(SysTool.class, "deleteFile:", e);
		}
		return false;
	}

	/**
	 * 缓存写入磁盘文件
	 * 
	 * @param buf 写入的byte数组
	 * @param fileName 写入磁盘文件名称及路径
	 * @param append 是否追加
	 * @return
	 */
	public static boolean writeFile(byte[] buf, String fileName, boolean append) {
		try (FileOutputStream os = new FileOutputStream(fileName, append)){
            // 写入字节数据
            os.write(buf);
            return true;
        } catch (Exception e) {
        	Log4j2Tool.error(SysTool.class, "writeFile:", e);
        	return false;
        }
	}

	/**
	 * 文本写入到指定文件
	 * @param fileName 文本文件路径+名称
	 * @param content 写入内容
	 * @param charset 写入编码
	 * @return true if success, or return false
	 */
	public static boolean writeTextFile(String fileName, String content, String charset){
		try{
			String path = getFilePath(fileName);
			dirExists(path,true);
			
			File file=new File(fileName);
			if (file.exists())
				file.delete();

			file.createNewFile();
			FileOutputStream out=new FileOutputStream(file,true);
			out.write(content.getBytes(charset));
			StreamTool.closeOutputStream(out);
			return true;
		 }catch(IOException e){
			Log4j2Tool.error(SysTool.class, "writeTextFile:", e);
			return false;
		 }
	}
	
	/**
	 * 文本文件读取操作
	 * @param fileName
	 * @param encoding
	 * @return
	 */
	public static String readTxtFile(String fileName, String encoding){
    	StringBuffer buf = null;
    	InputStreamReader isr = null;
        BufferedReader br = null;

        try{
            File file=new File(fileName);
            if(fileExists(fileName)==1){
            	buf = new StringBuffer();
            	isr = new InputStreamReader(new FileInputStream(file),encoding);
                br = new BufferedReader(isr);
                String lineTxt = null;
                while((lineTxt = br.readLine())!=null){
                	buf.append(lineTxt).append(System.lineSeparator());
                }
            }
        } catch (Exception e) {
        	Log4j2Tool.error(SysTool.class, "readTxtFile:", e);
        }
        
        //关闭reader
        StreamTool.closeReader(br);
        StreamTool.closeReader(isr);

        return (buf!=null ? buf.toString():null);
    }

	/**
	 * 文本文件读取操作
	 * @param is
	 * @param encoding
	 * @return
	 */
	public static String readTxtFile(InputStream is, String encoding){
    	StringBuffer buf = null;
    	InputStreamReader isr = null;
        BufferedReader br = null;

        try{
            buf = new StringBuffer();
            isr = new InputStreamReader(is, encoding);
            br = new BufferedReader(isr);
            String lineTxt = null;
            while((lineTxt = br.readLine())!=null){
            	buf.append(lineTxt).append(System.lineSeparator());
            }
        } catch (Exception e) {
        	Log4j2Tool.error(SysTool.class, "readTxtFile:", e);
        }

        //关闭reader
        StreamTool.closeInputStream(is);
        StreamTool.closeReader(br);
        StreamTool.closeReader(isr);

        return (buf!=null ? buf.toString():null);
    }

	/**
	 * 文件拷贝功能
	 * by @author lms 2020.06.22
	 * @param oldFile 被复制文件
	 * @param newFile 复制出的新文件
	 * @return
	 */
	public static boolean copyFile(String strOldFile, String strNewFile) {
		File fileOld = new File(strOldFile);
		if (!fileOld.exists()) 
			return false;

		boolean ret;
		InputStream in = null;
		FileOutputStream out = null;

		try {
			in = new FileInputStream(fileOld);
			out = new FileOutputStream(strNewFile);

			int read = 0;
			byte[] buf = new byte[1024];
			while ((read = in.read(buf)) != -1) { 
				out.write(buf, 0, read);
			}
			out.flush();
			ret = true;
		}catch(Exception e) {
			Log4j2Tool.error(SysTool.class, "copyFile:", e);
			ret = false;
		}

		StreamTool.closeOutputStream(out);
		StreamTool.closeInputStream(in);
		return ret;
	}

	/**
	 * 判断目录是否存在，并根据参数决定是否创建未存在的文件夹
	 * @param path disk path
	 * @param create if path do not exists, indicate whether to create it
	 * @return -1-异常; 0-文件夹不存在; 1-存在指定文件夹 */
	public static int dirExists(String path, boolean create){
		try{
			File file = new File(path);
			boolean exist = file.exists();
			if (exist || (create && file.mkdirs()))
				return 1;
			
			return 0;
		}catch (Exception e){
			Log4j2Tool.error(SysTool.class, "dirExists:", e);
			return -1;
		}
	}

	/**
	 * 获取文件路径
	 * @param fileName
	 * @return file path of file name
	 * @author lms 2016.07.06
	 */
	public static String getFilePath(String fileName){
		try{
			File file = new File(fileName);
			return file.getParentFile().getPath();
		}catch(Exception e){
			Log4j2Tool.error(SysTool.class, "getFilePath:", e);
			return null;
		}
	}

	/**
	 * 获取文件名
	 * @param fileName
	 * @return file name
	 * @author lms 2023.08.30
	 */
	public static String getFileName(String fileName){
		try{
			File file = new File(fileName);
			return file.getName();
		}catch(Exception e){
			Log4j2Tool.error(SysTool.class, "getFileName:", e);
			return null;
		}
	}

	/**
	 * 获取文件后缀
	 * @param fileName
	 * @return file extention, 如 ".jpg"
	 * @author lms 2022.12.22
	 */
	public static String getFileExt(String fileName){
		if (fileName.indexOf(".")==-1)
			return "";

		return fileName.substring(fileName.lastIndexOf(".")).toLowerCase();
	}

	/**
	 * 获取应用程序路径
	 * @return full path
	 * @author lms 2016.08.23
	 */
	public static String getApplicationPath(){
		return System.getProperty("user.dir");
	}

	/**
	 * to sleep for millisecond
	 * @param millis
	 */
	public static void sleep(long millis){
		try {
			Thread.sleep(millis);
		} catch (InterruptedException e) {
			Log4j2Tool.error(SysTool.class, "sleep:", e);
		}
	}
	
	/**
	 * 返回指定行数的换行字符串
	 * @param count line number
	 * @return
	 */
	public static String lineSeparator(int lines) {
		String ret = "";
		for(int i=0; i<lines; i++)
			ret += System.lineSeparator();
		return ret;
	}
	
	//////////////////////////////////////////// other function ///////////////////////////////////////

	/**
	 * 生成GUID
	 * @param delimiter 分隔符，默认guid生成后是 "-" 拼接在一起，此符号可以由分隔符替代
	 * @return
	 */
	public static String makeUUID(String delimiter){
		String ret = UUID.randomUUID().toString();
		return ret.replace("-", delimiter);
	}

	/**
	 * to get integer random value between minValue and maxValue
	 * @param minValue minimum of random
	 * @return value of random over than minValue
	 * @author lms 2016.08.28
	 */
	public static int getRandomNum(int minValue, int maxValue){
		return (int)(minValue+Math.random()*(maxValue-minValue+1));
	}
	
	/**
	 * to calculate byte[] checksum
	 * @param buf
	 * @param len
	 * @return
	 */
	public static short getChecksum(byte[] buf, int len){
		short sum = 0;
		for (int i=0; i<len; i++){
			sum += buf[i];
		}
		sum = (short) ((sum % 256) ^ 0xff);
		return sum;
	}
	
	public static short[] getCRC16(byte[] buf, int len)
	{
		int crc16 = 0;
	    for(int i=0; i<len; i++){
	    	crc16  = (char)(( crc16 >> 8) | (crc16 << 8));
	    	crc16 ^= buf[i] & 0xff;
	    	crc16 ^= (char)(( crc16 & 0xFF) >> 4);
	    	crc16 ^= (char)(( crc16 << 8) << 4);
	    	crc16 ^= (char)((( crc16 & 0xFF) << 4) << 1);
	    }
	    short[] ret = new short[2];
	    ret[0] = (short) (crc16/256);
	    ret[1] = (short) (crc16%256);
	    return ret;
	}
	
	public static Class<?> getClass(String className) {
		try {
			return Class.forName(className);
		}catch(Exception e) {
			return null;
		}
	}
	
	/**
	 * 递归创建目录
	 * @param dirPath linux 目录，如/var/cdn/html
	 */
	public static void deepMkDir(String dirPath) {
		String[] pathDirs = dirPath.split("/");
		File file = null;
		String path = "";
		for(String dir : pathDirs ) {		
			if (!"".equals(dir)) {
				path += "/" + dir;
				file = new File(path);
				if (!file.exists()) {
					file.mkdirs();
				}
			}
		}
	}

	public static void main(String[] args) {
		deepMkDir("d:\\a\\b\\c");
	}
}
